在今天的文章中,我們將深入探討如何在 YAML 文件中應用條件邏輯與變數,來實現更靈活且可擴展的 CI/CD 流程。隨著專案複雜度增加,僅依賴基礎的 YAML 設定可能無法滿足多環境、跨平台或動態調整的需求,因此,我們可以藉助條件語句與變數,來創建可根據需求進行靈活配置的Pipeline。
YAML (YAML Ain't a Markup Language / Yet Another Markup Language) 是一種輕量級、可讀性高的資料格式,非常適合用來定義 CI/CD Pipelines。它以簡潔的語法,能夠幫助團隊更快地管理和佈署應用程式。尤其在 DevOps 實踐中,YAML 是定義自動化流程的首選格式之一。
YAML-based Pipeline 的配置方式,讓我們能夠靈活地定義 CI/CD 工作流程,並且完全由程式碼控制。可以輕鬆地集成版本控制,從而提升可維護性和透明度。
YAML 文件格式簡單易懂,具有以下幾個特點:
條件邏輯允許我們根據某些條件(例如分支、變數值或其他環境參數)來決定是否執行某些步驟。這對於多環境佈署、多階段測試或跨平台應用程式開發尤為重要。
在 Azure Pipelines 的 YAML 文件中,我們可以使用 condition
關鍵字來設定條件,這些條件可以基於 pipeline 執行時的上下文,例如分支名稱、構建狀態、變數值等。
示例:針對不同的分支執行不同的步驟
steps:
- script: echo "This runs on all branches."
displayName: 'Run on all branches' # 此步驟會在所有分支上執行
- script: echo "This runs only on the main branch."
displayName: 'Run on main branch only' # 這一步驟僅在 main 分支執行
condition: eq(variables['Build.SourceBranch'], 'refs/heads/main') # 使用條件邏輯檢查當前分支是否為 main 分支
- script: echo "This runs only on feature branches."
displayName: 'Run on feature branches' # 這一步驟僅在 feature 分支執行
condition: startsWith(variables['Build.SourceBranch'], 'refs/heads/feature/') # 使用條件邏輯檢查當前分支是否為 feature 分支
在這個範例中,根據當前構建的分支不同,會有不同的指令被執行。當應用於多環境或多分支開發時,條件邏輯能夠幫助 CI/CD 流程更加自動化。
變數是一種強大的工具,可以讓我們在 YAML Pipeline中輕鬆重複使用值,避免在不同步驟中重複定義相同內容。Azure Pipelines 支持多種類型的變數,包括全域變數、區域變數,甚至可以從外部服務(如 Azure Key Vault)提取機密變數。
如果我們的應用需要使用敏感資訊(如 API 密鑰、資料庫連接字串),可以將這些變數設置為「機密變數」,並透過 Azure Key Vault 等秘鑰管理工具來保護這些資訊。這樣可以確保敏感資料不會直接暴露在 YAML 文件中。
基本變數示例:
variables:
pythonVersion: '3.9' # 定義 Python 版本號
projectName: 'MyApp' # 定義專案名稱
steps:
- script: echo "Building $(projectName) using Python $(pythonVersion)"
displayName: 'Display Project and Python Version' # 顯示專案名稱和 Python 版本
- script: |
python -m pip install --upgrade pip
pip install -r requirements.txt
displayName: 'Install dependencies for $(projectName)' # 安裝專案所需的依賴包
在這個例子中,我們定義了 pythonVersion
和 projectName
兩個變數,然後在不同的步驟中使用它們。這樣可以提高可讀性,並且未來修改變數時,只需改動一處即可。
現在我們將結合條件邏輯與變數,展示一個更實際的 CI/CD Pipeline示例。在這個示例中,我們將根據分支名稱來自動化佈署應用程式至不同的環境,並使用變數來設定不同的環境配置。
示例:基於分支進行環境佈署
variables:
devEnvName: 'dev-environment' # 定義開發環境的名稱
prodEnvName: 'prod-environment' # 定義正式環境的名稱
containerRegistry: 'myDockerRegistry' # 定義容器註冊表
repository: 'myDockerRepo/myApp' # 定義容器庫的存儲庫名稱
stages:
- stage: Build
jobs:
- job: BuildApp
pool:
vmImage: 'ubuntu-latest' # 指定構建作業使用的虛擬機映像
steps:
- script: echo "Building the application..."
displayName: 'Build the app' # 顯示正在構建應用程式
- task: Docker@2
inputs:
containerRegistry: $(containerRegistry) # 從變數中取得容器註冊表
repository: $(repository) # 從變數中取得容器庫存儲庫
command: build # 執行 Docker 的構建指令
Dockerfile: '$(Build.SourcesDirectory)/Dockerfile' # 指定 Dockerfile 的位置
tags: |
$(Build.BuildId) # 使用構建 ID 作為標籤
- stage: DeployToDev
dependsOn: Build # 此階段依賴於 Build 階段
condition: eq(variables['Build.SourceBranch'], 'refs/heads/develop') # 僅在 develop 分支執行此佈署步驟
jobs:
- job: DeployToDev
steps:
- script: echo "Deploying to $(devEnvName)"
displayName: 'Deploy to Development Environment' # 顯示正在佈署到開發環境
- stage: DeployToProd
dependsOn: Build # 此階段依賴於 Build 階段
condition: eq(variables['Build.SourceBranch'], 'refs/heads/main') # 僅在 main 分支執行此佈署步驟
jobs:
- job: DeployToProd
steps:
- script: echo "Deploying to $(prodEnvName)"
displayName: 'Deploy to Production Environment' # 顯示正在佈署到正式環境
在這個例子中,我們定義了兩個佈署階段(DeployToDev
和 DeployToProd
),根據當前的分支是否為 develop
或 main
來決定佈署的環境。此外,我們還使用了變數來定義環境名稱與容器庫地址,這樣讓Pipeline的配置更加靈活。
隨著專案規模的擴大,可能會出現多個Pipeline 共用同樣的步驟或配置。這時候我們可以使用模板 (templates) 來將重複的部分抽取出來,提升Pipeline的可重用性。
示例:提取模板
首先,創建一個模板檔案 build-template.yml
:
parameters:
- name: pythonVersion
type: string
default: '3.9' # 定義模板的參數,預設 Python 版本為 3.9
steps:
- task: UsePythonVersion@0
inputs:
versionSpec: ${{ parameters.pythonVersion }} # 使用模板參數來指定 Python 版本
displayName: 'Use Python ${{ parameters.pythonVersion }}' # 顯示使用的 Python 版本
- script: |
python -m pip install --upgrade pip
pip install -r requirements.txt
displayName: 'Install dependencies' # 安裝依賴
然後,在主 YAML 文件中引用這個模板:
stages:
- stage: Build
jobs:
- job: BuildApp
pool:
vmImage: 'ubuntu-latest' # 使用 Ubuntu 最新的虛擬機映像進行構建
steps:
- template: build-template.yml
parameters:
pythonVersion: '3.10' # 使用模板並指定 Python 版本為 3.10
這樣我們可以簡化主 YAML 文件的內容,並通過模板來管理重複的構建步驟。
今天我們深入探討了如何在 YAML 文件中使用條件邏輯與變數來實現靈活的 CI/CD 流程。透過這些進階技術,能夠根據實際需求動態配置Pipeline,並減少重複性配置,提升專案的可維護性。隨著專案的擴展,會發現這些技巧可以讓我們的 CI/CD 流程變得更加智慧與高效!
文章的最後,再次提醒大家,YAML對縮排是相當敏感的,佈署至正式環境前,謹慎檢查啊~~~。゚ヽ(゚´Д`)ノ゚。
圖片來源
明天我們將進入容器(Container)的世界,介紹容器化技術(Containerization)如何改變應用程式的開發與佈署流程。我們將學習 Docker 的基礎概念,並理解如何將 Docker 與 CI/CD 管道整合,實現更加靈活且可靠的佈署策略~
https://www.redhat.com/en/topics/automation/what-is-yaml
https://www.cloudbees.com/blog/yaml-tutorial-everything-you-need-get-started
https://www.commonwl.org/user_guide/topics/yaml-guide.html
https://yaml.irz.fr/key-value-pairs.html
https://www.runoob.com/w3cnote/yaml-intro.html